package com.gitee.cui.security.crypto;

import lombok.extern.slf4j.Slf4j;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import java.security.SecureRandom;

/**
 * 对称加密算法演示，通过一个密钥进行加密和解密
 * @author cuiqingqiang
 * @version 1.0
 * @date 2021/11/4 14:04
 **/
@Slf4j
public class DESCrypto {

    public static void main(String[] args) throws Exception {
        // 待加密数据
        String plain = "123456";
        // 密码，长度必须是8的倍数
        String password = "12345678";

        // 加密后的数据
        byte[] data = DESCrypto.encrypt(plain.getBytes(), password);
        log.info("待加密数据：{}，加密后数据：{}", plain, new String(data));

        // 解密数据
        byte[] result = DESCrypto.decrypt(data, password);
        log.info("解密后数据：{}", new String(result));
    }

    /**
     * 解密数据
     * @param data 待解密数据
     * @param password 密钥
     * @return 解密后的数据
     */
    private static byte[] decrypt(byte[] data, String password) throws Exception {
        // DES解密需要一个可信任的随机数
        SecureRandom random = new SecureRandom();
        // 创建一个DESKeySpec对象
        DESKeySpec keySpec = new DESKeySpec(password.getBytes());
        // 创建一个工厂
        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
        // 构造一个SecretKey
        SecretKey secretKey = keyFactory.generateSecret(keySpec);
        // 构造一个Cipher并初始化为解密
        Cipher cipher = Cipher.getInstance("DES");
        cipher.init(Cipher.DECRYPT_MODE, secretKey, random);
        // 真正执行解密
        return cipher.doFinal(data);
    }

    /**
     * 数据加密
     * @param bytes 待加密数据
     * @param password 密钥
     * @return 加密后数据
     */
    private static byte[] encrypt(byte[] bytes, String password) throws Exception {
        // DES算法要求一个可信任的随机数
        SecureRandom random = new SecureRandom();
        // 创建一个密钥描述符对象
        DESKeySpec keySpec = new DESKeySpec(password.getBytes());
        // 创建一个密钥工厂
        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
        // 将DESKeySpec对象转换为SecretKey对象
        SecretKey secretKey = keyFactory.generateSecret(keySpec);
        // Cipher对象实际完成加密操作
        Cipher cipher = Cipher.getInstance("DES");
        cipher.init(Cipher.ENCRYPT_MODE, secretKey, random);
        // 真正加密操作
        return cipher.doFinal(bytes);
    }
}
